package com.hxzy.config.interceptor.impl;

import cn.hutool.core.util.StrUtil;
import cn.hutool.crypto.SecureUtil;
import cn.hutool.json.JSONUtil;
import com.hxzy.common.annon.RepeatSubmit;
import com.hxzy.common.util.HttpHelper;
import com.hxzy.config.filter.RepeatedlyRequestWrapper;
import com.hxzy.config.interceptor.AbstractRepeatSubmitInterceptor;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import javax.servlet.http.HttpServletRequest;
import java.util.concurrent.TimeUnit;

/**
 * 分布式锁
 * 注解给 springmvc，告诉它这个拦截器
 */
@Component
public class RedissionRepeatSubmit extends AbstractRepeatSubmitInterceptor {

    @Autowired
    private RedissonClient redissonClient;


    @Override
    protected boolean isRepeatSubmit(HttpServletRequest request, RepeatSubmit repeatSubmit) {
        //当前参数
        String nowParam="";
        //读取参数 ( form body  json数据   POST/PUT [content-type:application/json])
        if(request instanceof RepeatedlyRequestWrapper){
            RepeatedlyRequestWrapper repeatedlyRequest = (RepeatedlyRequestWrapper) request;
            nowParam= HttpHelper.getBodyString(repeatedlyRequest);
        }

        //提交数据从流中读不到,再看一看它的参数在不在  请求参数中 (post[content-type: application/x-www-form-urlencoded]   ,get)
        // request.getParameter()
        if(StrUtil.isBlank(nowParam)){
            nowParam= JSONUtil.toJsonStr( request.getParameterMap());
        }

        String token=request.getHeader("Authorization");
        //构造 redis的key (必须唯一，不能使用UUID)   前缀:url地址:自己【令牌,现在只有模拟】：md5(参数)
        String md5Data= SecureUtil.md5(nowParam);
        String redisKey="repeat_submit:"+ request.getRequestURI()+":"+token+":"+md5Data;

        RLock  rLock=this.redissonClient.getFairLock(redisKey);

        //加锁
        try {
            if(rLock.tryLock(0,repeatSubmit.interval(),TimeUnit.MILLISECONDS)){
                return false;
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        //不要释放 , 相当于 删除redis中的redisKey
        //rLock.unlock();
        return true;
    }
}
